package com.zhanghe.study.springboot.configuration.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * @author zh
 * @date 2021/8/10 10:55
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 对不同的请求进行不同程度的认证
        http.formLogin()
                .loginPage("/login.html")  // 自定义编写登录页面
                .loginProcessingUrl("/user/login") // 登录访问路径
                .defaultSuccessUrl("/index") // 登陆成功之后跳转路径
                .and().logout().logoutUrl("/logout") // 退出登录的路径
                .logoutSuccessUrl("/index") // 退出登录成功的页面
                .and()
                .authorizeRequests() // // 配置请求级别的认证
                .antMatchers("/","/test/","/hello","/body").permitAll() // permitAll表示可以直接访问，不需要认证
                .antMatchers("/user").authenticated() //authenticated表示必须已经登录了系统
                .antMatchers("/admin/").hasAuthority("admin") // hasAuthority用户具备该权限可以访问
                .antMatchers("/teacher/").hasAnyAuthority("admin","teacher")  // hasAnyAuthority用户具备其中一个权限就可以访问
                .antMatchers("/super/").hasRole("admin")  //hasRole用户具备该角色可以访问，会拼接一个ROLE_前缀，使用的是角色是 ROLE_admin
                .antMatchers("/student/").hasAnyRole("admin","teacher","student") // hasAnyRole如果用户具备其中一个角色就可以访问
                .antMatchers("/school/").access("hasRole('admin')") //access使用给定的spel表达式来计算结果
                .antMatchers("/ss/").anonymous()  // anonymous允许匿名用户访问
                .antMatchers("/supper/").denyAll() // denyAll拒绝所有访问
                .antMatchers("/full/").fullyAuthenticated() //fullyAuthenticated 用户需要是完整认证(不是通过remeber-me功能认证的)允许访问
                .antMatchers("/ip/").hasIpAddress("127.0.0.1") // hasIpAddress 请求来自指定ip可以访问
                .antMatchers("/reme/").rememberMe() // 用户通过remember-me功能认证的允许访问
                .anyRequest().authenticated() // 其他需要认证
                .and()
                .requiresChannel().anyRequest().requiresSecure() //requiresSecure配置需要https来进行访问  requiresInsecure配置需要http来进行访问
                .and()
                .rememberMe().tokenValiditySeconds(3600).key("zhang") // rememberMe功能，保存时间3600s，rememberMe是将token存储在cookie中的，token包括用户名、密码、过期时间和私钥(key)
                .and()
                .exceptionHandling().accessDeniedPage("/unauth.html") // 配置没有权限访问的自定义页面
                .and()
                .csrf().disable() // 关闭csrf跨站请求伪造防护
                // 设置一个用户只能在一个设备上登录 设置最大会话数
                .sessionManagement().maximumSessions(1)
                .maxSessionsPreventsLogin(true) // 禁止后来者登录

        ;

    }
}
